﻿using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using SuperRyoninRPG.Characters;
using SuperRyoninRPG.Display;

namespace SuperRyoninRPG.Main
{
	/// <summary>
	///     タイルの衝突検出と応答動作を制御します。
	/// </summary>
	public enum TileCollision
	{
		/// <summary>
		///     通り抜け可能なタイルは、プレイヤーの動きをまったく妨げないタイルです。
		/// </summary>
		Passable = 0,

		/// <summary>
		///     通り抜け不能なタイルは、プレイヤーがまったく通り抜けできないタイルです。
		///     このタイルは完全にソリッドです。
		/// </summary>
		Impassable = 1,

		/// <summary>
		///     プラットフォーム タイルは、プレイヤーがその上にいるとき以外は、通り抜け可能な
		///     タイルのように動作するタイルです。プレイヤーはプラットフォームの上をジャンプして
		///     通り抜けたり、左右に移動したりできますが、プラットフォームの上から落下することは
		///     できません。
		/// </summary>
		Platform = 2,

		Breakable = 3,
	}

	public enum State
	{
		Normal,
		Bumped
	}

	/// <summary>
	///     タイルの外観と衝突動作を格納します。
	/// </summary>
	public class Tile
	{

		public const int Width = 32;
		public const int Height = 32;
		private const string FolderPath = "Images/Tiles/";


		public static readonly Vector2 Size = new Vector2(Width, Height);
		public TileCollision Collision { get; set; }
		private readonly Texture2D texture;
		protected Stage Stage;
		private int x;
		private int y;

		protected Vector2 Shift;

		public int DisplayX { get { return x * Width; } }
		public int DisplayY { get { return y * Height; } }
		
		public Texture2D Texture
		{
			get { return texture ?? (Animation != null ? Animation.Texture:null); }
		}

		private Animation animation;

		public Animation Animation
		{
			get
			{
				if (animations.Count !=0)
				{
					return this.animations[this.state.ToString()];
				}
				return this.animation;
			}
			set { this.animation = value; }
		}

		private State state;

		public State State
		{
			get { return state; }
			set
			{
				state = value;
				this.splite.PlayAnimation(animations[value.ToString()]);
			}
		}



		private readonly Dictionary<string,Animation> animations =new Dictionary<string, Animation>();

		private AnimationPlayer splite;

		/// <summary>
		///     新しいタイルを構築します。
		/// </summary>
		public Tile(TileCollision collision, Stage stage, int x, int y)
		{
			this.Collision = collision;
			this.Stage = stage;
			this.x = x;
			this.y = y;

			LoadContent();
		}

		private void LoadContent()
		{
			//throw new System.NotImplementedException();
		}

		/// <summary>
		///     新しいタイルを構築します。
		/// </summary>
		public Tile(Texture2D texture, TileCollision collision, Stage stage, int x, int y)
			: this(collision, stage, x, y)
		{
			this.texture = texture;
		}

		/// <summary>
		///     新しいタイルを構築します。
		/// </summary>
		public Tile(Animation animation, TileCollision collision, Stage stage, int x, int y)
			: this(collision, stage, x, y)
		{
			this.Animation = animation;
			this.splite.PlayAnimation(animation);
		}

		/// <summary>
		///     新しいタイルを構築します。
		/// </summary>
		public Tile(string name, TileCollision collision, Stage stage, int x, int y,int frameWidth)
			: this(collision, stage, x, y)
		{
			string path = Path.Combine(FolderPath, name);
			LoadAnimations(path, frameWidth);
			this.State = State.Normal;
		}

		public void LoadAnimations(string imagesPath, int frameWidth)
		{
			foreach (string characterState in Enum.GetNames(typeof(State)))
			{
				this.LoadAnimation(characterState, imagesPath, frameWidth);
			}
		}

		public void LoadAnimation(string tileState, string imagesPath, int frameWidth)
		{
			string path = Path.Combine(imagesPath, tileState);
			var texture = this.Stage.Content.Load<Texture2D>(path);
			var newAnimations = new Animation(texture, frameWidth, 0.15f, true);

			this.animations.Add(tileState, newAnimations);
		}

		public virtual void Bumped()
		{
			
		}

		public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
		{
			var rectangle = new Rectangle(DisplayX - (int)Stage.StagePosision + (int)Shift.X, DisplayY + (int)Shift.Y, Tile.Width, Tile.Width);
			
			if (this.texture != null)
			{
				spriteBatch.Draw(texture, rectangle, null, Color.White);
			}
			else
			{
				var displayPosition = new Vector2((DisplayX + Tile.Width / 2) - this.Stage.StagePosision + (int)Shift.X, DisplayY + Tile.Height + (int)Shift.Y);

				this.splite.Draw(gameTime, spriteBatch, displayPosition, new SpriteEffects());
			}
			
		}

		public virtual void Update(GameTime gameTime)
		{

		}
	}
}